`timescale 1ns/1ps
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2023 All rights reserved
// *********************************************************************************
// Project Name : 
// Author       : Dark
// Create Time  : 2023-01-31 10:49:31
// Revise Time	: 2023-01-31 10:49:31
// File Name    : ctrl_gen.sv
// Abstract     :
`include "defines.svh"

module ctrl_gen (
	input	logic	[31:0]	instr,		// instruction
	// control signals
	output 	logic			wb_en,	 	//Register bank write enable
	output 	logic			alu_srcA,	//alu operand A
	output 	logic	[ 1:0]	alu_srcB,	//alu operand B
	output 	logic	[ 3:0]	alu_ctrl,	//alu control
	output 	logic	[ 3:0]	branch,  	// pc 
	output 	logic			wb_src, 	// 0 alu or 1 mem
	output 	logic			mem_wr,  	// data mem write enable 
	output 	logic			mem_rd,  	// data mem read  enable 
	output 	logic	[ 2:0]	mem_ctrl 	// data mem control signal

);


//=================================================================================
// Signal declaration
//=================================================================================

	logic	[6:0]	op   			;
	logic	[2:0]	func3			;	
	logic	[6:0]	func7			;
		
	logic			vaild_LUI		;
	logic			vaild_AUIPC		;
	logic			vaild_I			;
	logic			vaild_R			;
	logic			vaild_JAL		;
	logic			vaild_JALR		;
	logic			vaild_B			;
	logic			vaild_LD		;
	logic			vaild_S			;	
//=================================================================================
// Body
//=================================================================================
	assign  op    		= instr[6:0]		;
	// assign  rs1   = instr[19:15]	;
	// assign  rs2   = instr[24:20]	;
	// assign  rd    = instr[11:7]	;
	assign  func3 		= instr[14:12]		;
	assign  func7 		= instr[31:25]		;
	assign	vaild_LUI	= (op==`OP_LUI	)	;
	assign	vaild_AUIPC	= (op==`OP_AUIPC)	;
	assign	vaild_I		= (op==`OP_I 	)	;
	assign	vaild_R		= (op==`OP_R 	)	;
	assign	vaild_JAL	= (op==`OP_JAL	)	;
	assign	vaild_JALR	= (op==`OP_JALR	)	;
	assign	vaild_B		= (op==`OP_B	)	;
	assign	vaild_LD	= (op==`OP_LD	)	;
	assign	vaild_S		= (op==`OP_S	)	;

	always_comb begin
		case (op)
			`OP_LUI	:	alu_ctrl = `ALU_B;				
			`OP_I 	:begin
					if ((func3 == `FUNC3_SLLI)||(func3 == `FUNC3_SRI))
						alu_ctrl = {func7[5],func3};
					else
						alu_ctrl = {1'b0,func3};
				end
			`OP_R 	:	alu_ctrl = {func7[5],func3};
			`OP_B 	:begin							// B-type ==> if		
					if (func3[2:1] == 2'b11 )   // bltu:110,bgeu:111
						alu_ctrl = `ALU_SLTU;
					else 
						alu_ctrl = `ALU_SLT;
				end
			`OP_AUIPC,`OP_LD,`OP_S,`OP_JAL,`OP_JALR:
						alu_ctrl = `ALU_ADD;
			default :	alu_ctrl = `ALU_ADD;
		endcase
	end

	assign	alu_srcA=	(vaild_AUIPC|vaild_JAL|vaild_JALR)?`A_PC:`A_RS1;
	assign	alu_srcB=	(vaild_B    |vaild_R)	?`B_RS2	 :
						(vaild_JAL  |vaild_JALR)?`B_4BYTE:`B_IMM;
	assign	wb_en	=	vaild_AUIPC |vaild_LUI|vaild_I|vaild_R|vaild_JAL|vaild_JALR|vaild_LD;
	assign	wb_src	=	vaild_LD  ?`SRC_MEM		:`SRC_ALU;
	assign	mem_wr	=	vaild_S;
	assign	mem_rd	=	vaild_LD;
	assign	mem_ctrl=	func3;
	assign 	branch  = 	vaild_JAL ?`BRAN_JAL 	:
						vaild_JALR?`BRAN_JALR	:
						vaild_B   ?{1'b0,func3}	:`BRAN_NOJ;
endmodule 
